﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed
#pragma once

#include "GcmpModelInterface.h"
#include "IDbObject.h"
#include "IElementMoveContext.h"
#include "Matrix4d.h"
#include "RegenDataId.h"
#include "INoElementIdDbObject.h"


namespace gcmp {

    
    class IElement;
    /// \brief 对象的变换组件的接口。
    class GCMP_MODEL_INTERFACE_EXPORT IElementTransformationComponent : public INoElementIdDbObject
    {
        DEFINE_CAST_DERIVED(gcmp::IElementTransformationComponent, gcmp::INoElementIdDbObject)
    public:
        /// \brief 创建一个默认的变换组件
        ///
        /// CanBeMoved和CanBeRotated返回Element本身的状态集对应属性值
        /// \param pElement 默认组件所属的Element
        /// \return OwnerPtr<IElementTransformationComponent> 变换组件
        static OwnerPtr<IElementTransformationComponent> CreateNoTransformationComponent();

        /// \brief 创建一个空的的变换组件
        ///
        /// CanBeMoved和CanBeRotated返回Element本身的状态集对应属性值
        /// \param pElement 空组件所属的Element
        /// \return OwnerPtr<IElementTransformationComponent> 变换组件
        static OwnerPtr<IElementTransformationComponent> CreateNullTransformationComponent();

        virtual ~IElementTransformationComponent() {}
#pragma region 通用操作
        /// \brief 对象的移动操作。
        /// \param moveContext 移动上下文信息。
        /// \return 返回true表示成功，false表示失败。
        virtual bool Translate(const IElementMoveContext& moveContext) = 0;

        /// \brief 对象的旋转操作。
        /// \param origin 旋转中心点。
        /// \param axis 旋转轴。
        /// \param angle 旋转角度。
        /// \return 返回true表示成功，false表示失败。
        virtual bool Rotate(const Vector3d& origin, const Vector3d& axis, double angle) = 0;

        /// \brief 对象的缩放操作。
        /// \param bastPt 缩放的基点。
        /// \param scaleFactor 缩放比例因子。
        /// \return 返回true表示成功，false表示失败。
        virtual bool Scale(const Vector3d& basePt, float scaleFactor) = 0;

        /// \brief 对象的转换操作。
        /// \param matrix 转换矩阵。
        /// \return 返回true表示成功，false表示失败。
        virtual bool Transform(const Matrix4d& matrix) = 0;

        /// \brief 对象的是否可移动。
        /// \param explanation 不可移动时，可以返回原因。
        /// \return 可移动则返回true；否则返回false。
        virtual bool CanBeMoved(std::wstring* explanation = nullptr) const = 0;

        /// \brief 对象的是否可旋转。
        /// \param explanation 不可旋转时，可以返回原因。
        /// \return 可旋转则返回true；否则返回false。
        virtual bool CanBeRotated(std::wstring* explanation = nullptr) const = 0;

        /// \brief 对象的是否可缩放。
        /// \param explanation 不可缩放时，可以返回原因。
        /// \return 可缩放则返回true；否则返回false。
        virtual bool CanBeScaled(std::wstring* explanation = nullptr) const = 0;

        /// \brief 获取对象修改关联更新id
        /// \param 发生变化的对象id
        /// \return 对象修改关联更新id
        static RegenDataId GetTransformedRdId(const ElementId& eId);

        /// \brief 标记对象修改关联更新id
        /// \param changedElement发生变化的对象
        /// \return void
        static void MarkTransformedRdId(IElement* changedElement);

        /// \brief 获取对象修改关联更新id
        /// \param changedElement发生变化的对象
        /// \return 对象修改关联更新id
        GCMP_OBSOLETE_API(2021/04/01, GetTransformedRdId(const ElementId & eId)) static RegenDataId GetTransformedRdId(const IElement* changedElement);
#pragma endregion 通用操作
    };

}// namespace gcmp


